#include <string.h>
#include "gkt_debug.h"
#include "gkt_user.h"
#include "user_fingerprint.h"
#include "gkt_user_fingerprint.h"
#include "gkt_os.h"
#include "gkt_system.h"

#include "fpalgorithm_interface.h"

#if defined(GKT_CONFIG_FPS_ENABLE)&&(GKT_CONFIG_FPS_ENABLE)
const uint32_t gkt_template_addr_start = FP_TEMPLATE_START_ADDR;
const uint32_t gkt_template_addr_end = FP_TEMPLATE_END_ADDR;

user_fingerprint_info_s g_user_fingerprint_info;

typedef struct{
	uint8_t	user_id_heb;//
	uint8_t	user_id_leb;//
}s_msg_deluser_data;

void user_fingerprint_delete_item(uint32_t user_index)
{
	const user_fingerprint_item_s *c_item;
	uint16_t match_id;

	s_msg_deluser_data deluser_data = {0};
	if(user_index < g_user_fingerprint.instance.item_available_nums){
		c_item = USER_FINGERPRINT_ITEM_C(user_index);
		deluser_data.user_id_heb = c_item->data[0];
		deluser_data.user_id_leb = c_item->data[1];
		match_id = deluser_data.user_id_heb<<8;
		match_id |= deluser_data.user_id_leb;
		G_FP_DeleteTemplate(match_id);
	}
}
#define user_fingerprint_reset_info	NULL
void user_fingerprint_reset_partition(void)
{
	G_FP_ClearTemplate();
}

static int user_fingerprint_compare(const uint8_t *data_in,const uint8_t *data_local)
{
	uint16_t	index_in,index_local;
	index_in = (data_in[0]<<8) | data_in[1];
	index_local = (data_local[0]<<8) | data_local[1];
	gkt_info("index_in=%d,index_local=%d\n",index_in,index_local);
	if(index_in == index_local)
		return 1;
	else
		return 0;
}

static int user_fingerprint_verify(uint32_t *user_id, uint32_t excluded_user_index,
										uint32_t authority,const uint8_t *data, uint32_t length)
{
	const user_fingerprint_item_s *c_item;
	uint32_t item_index;
	int matched, retval;

	gkt_unused(excluded_user_index);
	item_index = 0;
	if (authority >= GKT_USER_AUTH_MAX) {
		while (item_index < g_user_fingerprint.instance.item_available_nums) {
			c_item = USER_FINGERPRINT_ITEM_C(item_index);
			if (USER_ITEM_IS_USED(&c_item->header)
				&& ((uint32_t)c_item->data_length <= length)) 
			{
				matched = user_fingerprint_compare(data, c_item->data);
				if (matched) {
					*user_id = GKT_USER_ID_BUILD(c_item->header.authority.type,
									0,
									GKT_USER_TYPE_FINGERPRINT, 
									c_item->header.user_index);
					return GKT_USER_VERIFY_PASSED;
				}
			}
			item_index++;
		}
	}
	else if (authority < GKT_USER_AUTH_TEMPORARY) {
		while (item_index < g_user_fingerprint.instance.item_available_nums) {
			c_item = USER_FINGERPRINT_ITEM_C(item_index);
			if (USER_ITEM_IS_USED(&c_item->header)
				&& ((uint32_t)c_item->header.authority.type == authority)
				&& ((uint32_t)c_item->data_length <= length)) 
			{
				matched = user_fingerprint_compare(data, c_item->data);
				if (matched) {
					*user_id = GKT_USER_ID_BUILD(c_item->header.authority.type,
									0,
									GKT_USER_TYPE_FINGERPRINT, 
									c_item->header.user_index);
					return GKT_USER_VERIFY_PASSED;
				}
			}
			item_index++;
		}	
	}


	retval = GKT_USER_VERIFY_FAILED;
	return retval;
}

int user_fingerprint_verify_update(void)
{
	int retval;
	
	retval=G_FP_UpdateTemplate();
	gkt_info("G_FP_UpdateTemplate = %x\n",retval);
	return retval;
}

#define user_fingerprint_verify_finalize	NULL
#define user_fingerprint_enroll_init	NULL

static int user_fingerprint_enroll_run(const uint8_t *data, 
					uint32_t length)
{
	uint32_t i;
	gkt_unused(g_user_fingerprint_info);

	for (i = 0; i < length; i++)
		g_user_fingerprint.enroll_item.data[i] = data[i];

	g_user_fingerprint.enroll_item.data_length = (uint8_t)length;
	return GKT_USER_ENROLL_COMPLETE;
}

#define user_fingerprint_enroll_uninit	NULL
#define user_fingerprint_config	NULL
#define user_fingerprint_add_item	NULL

extern gkt_mutex_t fp_ipc_mutex;
int user_fingerprint_init(void)
{
	int maxTemplateNum=0,retval;
	uint32_t s_addr,flash_size;

	s_addr = FP_TEMPLATE_START_ADDR;
	flash_size = FP_TEMPLATE_FLASH_SIZE_DATA(FP_TEMPLATE_FLASH_SIZE);
	gkt_info("s_addr,flash_size = %x,%x\n",s_addr,flash_size);
	gkt_mutex_lock(fp_ipc_mutex, GKT_INFINITE);
	maxTemplateNum=G_FP_AlgorithmInit(s_addr,flash_size);
	gkt_mutex_unlock(fp_ipc_mutex);
	if(maxTemplateNum>0)
	{
			retval = GKT_SUCCESS;
			gkt_info("maxTemplateNum=%d\r\n",maxTemplateNum);
	}
	else
	{
			retval = GKT_EUNDESIRED;
			gkt_error("G_FP_AlgorithmInit fail[ret=%d]\r\n",maxTemplateNum);
	}

	return retval;
}

USER_TYPE_OPS_DEFINE(fingerprint);
user_fingerprint_s g_user_fingerprint = {
	.instance = {
		.type = GKT_USER_TYPE_FINGERPRINT,
		.flags = USER_INSTANCE_F_ITEM_UPDATE_DATA_ONLY_ENABLE,
		.c_ops = USER_TYPE_OPS_PTR(fingerprint),
		.c_partition_name = "UserFingerprint",

		.info = &g_user_fingerprint_info.common,

		.auth_user_maxnums = {
			GKT_USER_FINGERPRINT_ADMIN_MAXNUMS,
			GKT_USER_FINGERPRINT_NORMAL_MAXNUMS,
			GKT_USER_FINGERPRINT_GUEST_MAXNUMS,
		},

		.item_size = USER_FINGERPRINT_ITEM_SIZE,
		.item_data_maxsize = 0,
		.item_header = &g_user_fingerprint.enroll_item.header,
	},
};

#endif

